import java.util.Arrays;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;

/**
 Java 8 Stream
     常用【生成流、forEach、map、filter、limit、sorted、并行(parallel)程序、Collectors、统计】
     网站：https://www.runoob.com/java/java8-streams.html
 */
public class JDK_1 {
    public static void main(String[] args) {
        /**
         * 生成流
         *  在 Java 8 中, 集合接口有两个方法来生成流：
         *      stream() − 为集合创建串行流
         *      parallelStream() − 为集合创建并行流
         */
        List<String> s1 = Arrays.asList("abc", "", "bc", "efg", "abcd", "", "jkl");
        List<String> s2 = s1.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
        System.out.println(s1); // [abc, , bc, efg, abcd, , jkl]
        System.out.println(s2); // [abc, bc, efg, abcd, jkl]
        System.out.println("-----------------------------------------------------");
        /**
         * forEach
         *  Stream 提供了新的方法 'forEach' 来迭代流中的每个数据
         *  以下代码片段使用 forEach 输出了10个随机数：
         */
        Random random1 = new Random();
        random1.ints().limit(10).forEach(System.out::println);
        System.out.println("-----------------------------------------------------");
        /**
         * map
         *  map 方法用于映射每个元素到对应的结果
         *  以下代码片段使用 map 输出了元素对应的平方数：
         */
        List<Integer> s3 = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
        // 获取对应的平方数
        List<Integer> s4 = s3.stream().map( i -> i*i).distinct().collect(Collectors.toList());
        System.out.println(s3); // [3, 2, 2, 3, 7, 3, 5]
        System.out.println(s4); // [9, 4, 49, 25]
        System.out.println("-----------------------------------------------------");
        /**
         * filter
         *  filter 方法用于通过设置的条件过滤出元素
         *  以下代码片段使用 filter 方法过滤出空字符串：
         */
        List<String> s5 = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
        // 获取空字符串的数量
        long s6 = s5.stream().filter(string -> string.isEmpty()).count();
        System.out.println(s5); // [abc, , bc, efg, abcd, , jkl]
        System.out.println(s6); // 2
        System.out.println("-----------------------------------------------------");
        /**
         * limit
         *  limit 方法用于获取指定数量的流 
         *  以下代码片段使用 limit 方法打印出 10 条数据：
         */
        Random random2 = new Random();
        random2.ints().limit(10).forEach(System.out::println);
        System.out.println("-----------------------------------------------------");
        /**
         * sorted
         *  sorted 方法用于对流进行排序
         *  以下代码片段使用 sorted 方法对输出的 10 个随机数进行排序：
         */
        Random random3 = new Random();
        random3.ints().limit(10).sorted().forEach(System.out::println);
        System.out.println("-----------------------------------------------------");
        /**
         * 并行(parallel)程序
         *  parallelStream 是流并行处理程序的代替方法
         *  以下实例我们使用 parallelStream 来输出空字符串的数量：
         */
        List<String> s7 = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
        // 获取空字符串的数量
        long s8 = s7.parallelStream().filter(string -> !string.isEmpty()).count();
        System.out.println(s7); // [abc, , bc, efg, abcd, , jkl]
        System.out.println(s8); // 5
        System.out.println("-----------------------------------------------------");
        /**
         * Collectors
         *  Collectors 类实现了很多归约操作，例如将流转换成集合和聚合元素
         *  Collectors 可用于返回列表或字符串：
         */
        List<String> s9 = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
        List<String> s10 = s9.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
        System.out.println(s9); // [abc, , bc, efg, abcd, , jkl]
        System.out.println("筛选列表: " + s10); // 筛选列表: [abc, bc, efg, abcd, jkl]
        String s11 = s9.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", "));
        System.out.println("合并字符串: " + s11); // 合并字符串: abc, bc, efg, abcd, jkl
        System.out.println("-----------------------------------------------------");
        /**
         * 统计
         *  另外，一些产生统计结果的收集器也非常有用
         *  它们主要用于int、double、long等基本类型上，它们可以用来产生类似如下的统计结果。
         */
        List<Integer> s12 = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
        IntSummaryStatistics s13 = s12.stream().mapToInt((x) -> x).summaryStatistics();
        System.out.println(s12); // [3, 2, 2, 3, 7, 3, 5]
        System.out.println("列表中最大的数 : " + s13.getMax()); // 列表中最大的数 : 7
        System.out.println("列表中最小的数 : " + s13.getMin()); // 列表中最小的数 : 2
        System.out.println("所有数之和 : " + s13.getSum()); // 所有数之和 : 25
        System.out.println("平均数 : " + s13.getAverage()); // 平均数 : 3.5714285714285716
    }
}